using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using usm.SolDev.Common;
using usm.SolDev.UI.Db;
using System.Runtime.InteropServices;
using usm.SolDev.UI;
using usm.SolDev.DataBase.DataObjects;
using System.Runtime.Remoting.Messaging;
using usm.SolDev.DataBase.DataAccess;
using usm.SolDev.UI.Build;
using WeifenLuo.WinFormsUI.Docking;
using usm.SolDev.UI.Sys;
using usm.SolDev.UI.User;
using usm.SolDev.UI.Charting;
using System.IO;
using usm.SolDev.UI.Tabular;

namespace usm.SolDev.App
{
    public partial class MainForm : Form
    {
        #region Private data
        private bool allowChangeDocument = true;
        #endregion

        #region Open forms holders
        private RepositoryExplorer repositoryExplorer;
        private FilesBrowser fileBrowser;
        private List<EditorForm> openedEditors = new List<EditorForm>();
        private EditorForm currentEditorForm;
        private BuildMessages buildMessages;
        private BuildErrors buildErrors;
        private CodeExplorer codeExplorer;
        private List<ChartForm> openedCharts = new List<ChartForm>();
        private ChartForm currentChartForm;
        private ChartOptionsForm chartOptionsForm;
        #endregion

        #region Constructors
        /// <summary>
        ///     Default constructor
        /// </summary>
        public MainForm ()
        {
            InitializeComponent ();
            ShowWorksessionData();
        }

        #endregion
        
        #region Helpers
        /// <summary>
        ///     Show helper information in status bar.
        /// </summary>
        private void ShowWorksessionData ()
        {
            statusBarWorksession.Text = String.Format("Host: {0} | User: {1} | Db: {2} | Role: {3}", 
                    "localhost", WorksessionData.UserInfo.Login,  "soldev", WorksessionData.UserInfo.Group);
        }

        /// <summary>
        ///     Enable or disable form components when som operation is
        /// in progress.
        /// </summary>
        /// <param name="state"></param>
        private void EnableControls (bool state)
        {
            dockPanel.Enabled = state;
            menuStrip1.Enabled = state;

            if (state == false)
            {
                tssStatusLabel.Text = "Wait, operation in progress ... ";
                tssWaitImage.Visible = true;
            }
            else
            {
                tssStatusLabel.Text = "";
                tssWaitImage.Visible = false;
            }
        }
        #endregion

        #region Menu events handlers
        /// <summary>
        ///     Invoked each time a main menu item is clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mainMenuItemClicked(object sender, EventArgs e)
        {

            #region Exit 
            if (sender.Equals(menuItemExit))
            {
                Close ();
            }
            #endregion

            #region View repository
            else if (sender.Equals(menuItemViewRepository))
            {
                EnableControls(false);
                if (repositoryExplorer == null)
                {
                    repositoryExplorer = new RepositoryExplorer();
                    repositoryExplorer.Show(dockPanel);

                    repositoryExplorer.FormClosing  += new System.Windows.Forms.FormClosingEventHandler(FormClosingEvent);
                    repositoryExplorer.OpenProject += new RepositoryExplorer.OpenProjectDelegate(OpenProjectHandler);
                    repositoryExplorer.DeleteProjectNotify += new RepositoryExplorer.NotifyDeleteProjectDelegate(DeleteProjectHandler);
                    repositoryExplorer.ViewResultsProject += new RepositoryExplorer.ViewResultsDelegate(ViewProjectResultsHandler);
                    
                    repositoryExplorer.ViewTabularResultsProject += new RepositoryExplorer.ViewTabularResultsDelegate(ViewTabularProjectResultsHandler);
                }
                else
                {
                    repositoryExplorer.BringToFront();
                }
                EnableControls(true);
            }
            #endregion

            #region View About dialog
            else if (sender.Equals(this.aboutToolStripMenuItem))
            {
                AboutForm aboutForm = new AboutForm();
                EnableControls(false);
                aboutForm.ShowDialog();
                EnableControls(true);
            }
            #endregion

            #region View local files
            else if (sender.Equals(menuItemLocalFiles))
            {
                EnableControls(false);
                if (fileBrowser == null)
                {
                    fileBrowser = new FilesBrowser();
                    fileBrowser.Show(dockPanel);

                    fileBrowser.FormClosing += new System.Windows.Forms.FormClosingEventHandler(FormClosingEvent);
                    fileBrowser.OpenProject += new FilesBrowser.OpenProjectDelegate(OpenProjectHandler);
                }
                else
                {
                    fileBrowser.BringToFront();
                }
                EnableControls(true);
            }
            #endregion

            #region Save as
            else if (sender.Equals(menuItemFileSaveAs))
            {
                EnableControls(false);
                if (currentEditorForm != null)
                {
                    
                    SaveAsForm saveAsForm = new SaveAsForm(currentEditorForm.Project);
                    if (saveAsForm.ShowDialog() == DialogResult.OK)
                    {
                        currentEditorForm.Project.State = usm.SolDev.Common.Config.ObjectState.Original;
                    }
                }
                else
                {
                    new SolDevException("No project selected");
                }
                EnableControls(true);
                
            }
            #endregion

            #region New file
            else if (sender.Equals(menuItemFileNew))
            {
                EnableControls(false);
                ProjectDescriptor projectDescriptor = new ProjectDescriptor(null, null, null, WorksessionData.UserInfo.Id, 0, "New", DateTime.Now, WorksessionData.UserInfo.Name, "none");
                projectDescriptor.State = usm.SolDev.Common.Config.ObjectState.New;

                EditorForm editor = new EditorForm(projectDescriptor);
                editor.Show(dockPanel);
                editor.FormClosing += new System.Windows.Forms.FormClosingEventHandler(FormClosingEvent);
                openedEditors.Add(editor);
                EnableControls(true);
            }
            #endregion

            #region Save file (for new project invoke save as form)
            else if (sender.Equals(menuItemFileSave))
            {
                EnableControls(false);
                if (currentEditorForm != null && currentEditorForm.Project != null)
                {
                    if (currentEditorForm.Project.State == usm.SolDev.Common.Config.ObjectState.New)
                    {
                        SaveAsForm saveAsForm = new SaveAsForm(currentEditorForm.Project);
                        if (saveAsForm.ShowDialog() == DialogResult.OK)
                        {
                            currentEditorForm.Project.State = usm.SolDev.Common.Config.ObjectState.Original;
                        }
                        EnableControls(true);
                    }
                    else
                    {
                        if (currentEditorForm.Project.State == usm.SolDev.Common.Config.ObjectState.Modified)
                        {
                            (new SaveExistingProjectDelegate(SaveExistingProject)).BeginInvoke(currentEditorForm.Project, new AsyncCallback(SaveExistingProjectCallBack), null);
                        }
                    }
                }
                else
                {
                    new SolDevException("No project selected");
                    EnableControls(true);
                }

            }
            #endregion

            #region View build messages
            else if (sender.Equals(menuItemBuildMessages))
            {
                EnableControls(false);

                if (buildMessages == null)
                {
                    buildMessages = new BuildMessages();
                    buildMessages.Show(dockPanel);

                    buildMessages.FormClosing += new System.Windows.Forms.FormClosingEventHandler(FormClosingEvent);
                    
                }
                else
                {
                    buildMessages.BringToFront();
                }

                EnableControls(true);

            }
            #endregion

            #region Build errors
            else if (sender.Equals(menuItemBuildErrors))
            {
                EnableControls(false);

                if (buildErrors == null)
                {
                    if (currentEditorForm != null)
                    {
                        buildErrors = new BuildErrors(currentEditorForm.Project);
                    }
                    else
                    {
                        buildErrors = new BuildErrors(null);
                    }
                    
                    buildErrors.Show(dockPanel);
                    buildErrors.FormClosing += new System.Windows.Forms.FormClosingEventHandler(FormClosingEvent);
                    buildErrors.JumpToErrorLine += new BuildErrors.JumpToErrorLineDelegate(JumpToErrorLineEventHandler);
                }
                else
                {
                    buildErrors.BringToFront();
                }

                buildErrors.AppendLine("Error 21: Simple error message");
                buildErrors.AppendLine("Warning 22: Simple WARN message");

                EnableControls(true);
            }
            #endregion

            #region Compile action
            else if (sender.Equals(menuItemCompile) && currentEditorForm != null && currentEditorForm.Project != null)
            {
                EnableControls(false);
                if (buildMessages == null)
                {
                    buildMessages = new BuildMessages();
                    buildMessages.Show(dockPanel);

                    buildMessages.FormClosing += new System.Windows.Forms.FormClosingEventHandler(FormClosingEvent);
                    
                }
                else
                {
                    buildMessages.BringToFront();
                }

                buildMessages.ClearMessages();
                buildMessages.AppendMessage(String.Format("Start building on {0} ... ", DateTime.Now));

                usm.SolDev.Common.ProcessCompile compilerProc = new usm.SolDev.Common.ProcessCompile(currentEditorForm.Project.Program, currentEditorForm.Project.Description, false);
                (new StartCompileDelegate(StartCompilation)).BeginInvoke(compilerProc, new AsyncCallback(StartCompileCallBack), null);
                EnableControls(true);
            }
            #endregion

            #region Execute compiled program and collect results
            else if (sender.Equals(menuItemRun) && currentEditorForm != null && currentEditorForm.Project != null)
            {
                EnableControls(false);
                if (buildMessages == null)
                {
                    buildMessages = new BuildMessages();
                    buildMessages.Show(dockPanel);

                    buildMessages.FormClosing += new System.Windows.Forms.FormClosingEventHandler(FormClosingEvent);
                    
                }
                else
                {
                    buildMessages.BringToFront();
                }

                buildMessages.ClearMessages();
                buildMessages.AppendMessage(String.Format("Start building and execution on {0} ... ", DateTime.Now));

                usm.SolDev.Common.ProcessCompile compilerProc = new usm.SolDev.Common.ProcessCompile(currentEditorForm.Project.Program, currentEditorForm.Project.Description, true);
                compilerProc.Execute = true;
                (new StartCompileDelegate(StartCompilation)).BeginInvoke(compilerProc, new AsyncCallback(StartCompileCallBack), null);
                EnableControls(true);
            }
            #endregion

            #region System settings form invocation
            else if (sender.Equals(menuItemConnectionSettings))
            {
                EnableControls(false);
                SystemSettingsForm systemSettings = new SystemSettingsForm ();
                systemSettings.ShowDialog();
                EnableControls(true);
            }
            #endregion

            #region Code explorer tool window
            else if (sender.Equals(menuItemCodeExplorer))
            {
                EnableControls(false);

                if (codeExplorer == null)
                {
                    codeExplorer = new CodeExplorer();

                    if (currentEditorForm != null)
                    {
                        codeExplorer.ReloadProject(currentEditorForm.Project);
                    }
                    
                    codeExplorer.Show(dockPanel);
                    codeExplorer.FormClosing += new System.Windows.Forms.FormClosingEventHandler(FormClosingEvent);
                    codeExplorer.ExploreCode += new CodeExplorer.ExploreCodeElementDelegate(SeekToCodeElementHandler);
                }
                else
                {
                    codeExplorer.BringToFront();
                }

                EnableControls(true);

            }
            #endregion

            #region Options form invocation
            else if (sender.Equals(menuItemOptions))
            {
                EnableControls(false);
                OptionsForm systemSettings = new OptionsForm();
                systemSettings.ShowDialog();
                EnableControls(true);
            }
            #endregion

            #region Open project
            else if (sender.Equals(menuItemFileOpen))
            {
                EnableControls(false);

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    ProjectDescriptor projectDescriptor = (ProjectDescriptor)(new ProjectDescriptor()).LoadFromFile(openFileDialog.FileName);
                    projectDescriptor.FilePath = openFileDialog.FileName;

                    // Test if this project is already opened. Compare project ID's
                    foreach (EditorForm editorForm in openedEditors)
                    {
                        if (editorForm.Project.Id.Equals(projectDescriptor.Id))
                        {
                            editorForm.BringToFront();
                            EnableControls(true);
                            return;
                        }
                    }

                    projectDescriptor.State = usm.SolDev.Common.Config.ObjectState.Original;
                    EditorForm editor = new EditorForm(projectDescriptor);
                    editor.Show(dockPanel);
                    editor.FormClosing += new System.Windows.Forms.FormClosingEventHandler(FormClosingEvent);
                    openedEditors.Add(editor);
                }

                EnableControls(true);
            }
            #endregion

            #region Manage users and groups
            else if (sender.Equals(menuItemManageUsersAndGroups))
            {
                EnableControls(false);
                using (UserManagement userManagement = new UserManagement())
                {
                    userManagement.ShowDialog();
                }
                EnableControls(true);
            }
            #endregion
                 
            #region Chart options
            else if (sender.Equals(menuItemChartOptions))
            {
                EnableControls(false);

                if (chartOptionsForm == null)
                {
                    chartOptionsForm = new ChartOptionsForm();

                    if (currentChartForm != null)
                    {
                        chartOptionsForm.ChartData =  currentChartForm.ChartData;
                    }

                    chartOptionsForm.Show(dockPanel);
                    chartOptionsForm.FormClosing += new System.Windows.Forms.FormClosingEventHandler(FormClosingEvent);
                    chartOptionsForm.RefreshChart += new ChartOptionsForm.RefreshChartDelegate(RefreshChartHandler);
                }
                else
                {
                    chartOptionsForm.BringToFront();
                }
                EnableControls(true);
            }
            #endregion

            #region Clean
            else if (sender.Equals(menuItemClean))
            {
                EnableControls(false);
                if (buildMessages == null)
                {
                    buildMessages = new BuildMessages();
                    buildMessages.Show(dockPanel);

                    buildMessages.FormClosing += new System.Windows.Forms.FormClosingEventHandler(FormClosingEvent);

                }
                else
                {
                    buildMessages.BringToFront();
                }

                buildMessages.ClearMessages();
                buildMessages.AppendMessage("Cleaning project intermediate and temporary files ..");
                buildMessages.AppendMessage("Done, project is clean");
                EnableControls(true);
            }
            #endregion

            #region Close file
            else if (sender.Equals(menuItemFileClose) && currentEditorForm != null)
            {
                EnableControls(false);
                currentEditorForm.Close();
                EnableControls(true);
            }
            #endregion

            #region Default
            else
            {
                new SolDevException("Invalid menu command");
            }

            #endregion
        }

        #region Save existing project business logic
        /// <summary>
        ///     Save file logic (to database or to local file system)
        /// </summary>
        /// <param name="project"></param>
        private bool SaveExistingProject(ProjectDescriptor project)
        {
            try
            {

                if (project.Origin == usm.SolDev.Common.Constants.Application.Origins.fromFile)
                {
                    project.SaveToFile(project.FilePath);
                    currentEditorForm.Project.State = usm.SolDev.Common.Config.ObjectState.Original;

                }
                else
                {
                    if (project.Id == null || project.Id.Equals(Guid.Empty))
                    {
                        project.Id = Guid.NewGuid();
                    }

                    return DataProvider.DataBase.SaveProjectToRepository(project);
                }

                return true;
            }
            catch {}

            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="project"></param>
        private delegate bool SaveExistingProjectDelegate(ProjectDescriptor project);
        private void SaveExistingProjectCallBack(IAsyncResult ar)
        {
            try
            {
                bool operationResult = ((SaveExistingProjectDelegate)((AsyncResult)ar).AsyncDelegate).EndInvoke(ar);
                if (!IsDisposed && IsHandleCreated)
                {
                    BeginInvoke(new AfterSaveExistingProjectOperationCompletedDelegate(AfterSaveExistingProjectOperationCompleted), new object[] { operationResult});
                }
            }
            catch
            {
                BeginInvoke(new AfterSaveExistingProjectOperationCompletedDelegate(AfterSaveExistingProjectOperationCompleted), new object[] {false});
            }
        }

        /// <summary>
        ///     Complete the save operation, enable components
        /// </summary>
        /// <param name="success"></param>
        /// <returns></returns>
        private delegate void AfterSaveExistingProjectOperationCompletedDelegate (bool success );
        private void AfterSaveExistingProjectOperationCompleted(bool success)
        {
            EnableControls(true);
            if (success == false)
            {
                new SolDevException("Cannot complete save operation");
            }
        }
        #endregion

        #endregion

        #region Child forms event handlers
        /// <summary>
        ///     Catch events when child forms are closed. Clean up some 
        /// internal data.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void FormClosingEvent(object sender, FormClosingEventArgs e)
        {
            EnableControls(false);

            #region repository explorer
            if (sender == repositoryExplorer)
            {
                repositoryExplorer.Dispose();
                repositoryExplorer = null;
            }
            #endregion

            #region one of the editors form
            if (sender is EditorForm)
            {
                bool allowClose = true;

                // warn about unsaved files
                if (currentEditorForm != null && currentEditorForm.Project != null &&
                    (currentEditorForm.Project.State  == usm.SolDev.Common.Config.ObjectState.Modified ||
                     currentEditorForm.Project.State  == usm.SolDev.Common.Config.ObjectState.New)
                   )
                {
                    if (MessageBox.Show(String.Format("The project {0} has not been saved, continue anyway?", currentEditorForm.Project.Description), "Confirm", MessageBoxButtons.YesNo) == DialogResult.No)
                    {
                        allowClose = false;
                        e.Cancel = true;
                    }
                }

                if (allowClose == true)
                {
                    currentEditorForm = null;
                    foreach (EditorForm editorForm in openedEditors)
                    {
                        if (editorForm.Project.Id.Equals(((EditorForm)sender).Project.Id))
                        {
                            openedEditors.Remove(editorForm);
                            if (codeExplorer != null && codeExplorer.Project != null && editorForm.Project.Id.Equals(codeExplorer.Project.Id))
                            {
                                codeExplorer.ReloadProject(null);
                            }
                            break;
                        }
                    }

                    if (codeExplorer != null && openedEditors.Count == 0)
                    {
                        codeExplorer.ReloadProject(null);
                    }
                }
            }
            #endregion

            #region build messages
            if ( sender == buildMessages)
            {
                buildMessages.Dispose();
                buildMessages = null;
            }
            #endregion

            #region build errors
            if ( sender == buildErrors )
            {
                buildErrors.Dispose();
                buildErrors = null;
            }
            #endregion

            #region code explorer
            if (sender == codeExplorer)
            {
                codeExplorer.Dispose();
                codeExplorer = null;
            }
            #endregion

            #region one of the chart results form
            if (sender is ChartForm)
            {
                currentChartForm = null;
                foreach (ChartForm chartForm in openedCharts)
                {
                    if (chartForm.ChartData.Project.Id.Equals(((ChartForm)sender).ChartData.Project.Id))
                    {
                        openedCharts.Remove(chartForm);
                        chartForm.Close();
                        if ( chartOptionsForm != null && 
                             chartOptionsForm.ChartData != null && 
                             chartForm.ChartData.Project.Id.Equals(chartOptionsForm.ChartData.Project.Id))
                        {
                            chartOptionsForm.ChartData = null;
                        }
                        break;
                    }
                }
            }
            #endregion

            #region chart options
            if (sender == chartOptionsForm)
            {
                chartOptionsForm.Dispose();
                chartOptionsForm = null;
            }
            #endregion
            
            EnableControls(true);
        }

        /// <summary>
        ///     Is invoked when user double clicked on a project in 
        /// Repository explorer. The code have to check if the project with 
        /// this id has not been opened already.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="projectDescriptor"></param>
        private void OpenProjectHandler(object sender, ProjectDescriptor projectDescriptor)
        {
            EnableControls(false);
            // Test if this project is already opened. Compare project ID's
            foreach(EditorForm editorForm  in  openedEditors)
            {
                if (editorForm.Project.Id.Equals(projectDescriptor.Id))
                {
                    editorForm.BringToFront();
                    EnableControls(true);
                    return;
                }
            }

            projectDescriptor.State = usm.SolDev.Common.Config.ObjectState.Original;
            EditorForm editor = new EditorForm(projectDescriptor);
            editor.Show(dockPanel);
            editor.FormClosing += new System.Windows.Forms.FormClosingEventHandler(FormClosingEvent);
            openedEditors.Add(editor);
            EnableControls(true);
        }

        /// <summary>
        ///     This event handler is invoked when user select delete menu item from context
        /// menu of the database repository
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="projectDescriptor"></param>
        private void DeleteProjectHandler(object sender, string projectId)
        {
            EnableControls(false);
            foreach(EditorForm editorForm  in  openedEditors)
            {
                if (editorForm.Project.Id.Equals(new Guid(projectId)))
                {
                    editorForm.Close();
                    break;
                }
            }
            EnableControls(true);
        }

        /// <summary>
        ///     When user double click on a element in the code explorer, the editor window
        /// goes to the place where element is defined, and selects entire line
        /// </summary>
        /// <param name="sender">the sender object </param>
        /// <param name="projectDescriptor">the project descriptor for which this handler has been called</param>
        /// <param name="lineNumber">the line number on which the element is</param>
        /// <param name="offset">the offset of the symbol (zero actually :)) </param>
        /// <param name="length">the length of the line</param>
        private void SeekToCodeElementHandler(object sender, ProjectDescriptor projectDescriptor, int lineNumber, int offset, int length)
        {
            EnableControls(false);
            foreach (EditorForm editorForm in openedEditors)
            {
                if (editorForm.Project.Id.Equals(projectDescriptor.Id))
                {
                    allowChangeDocument = false;
                    editorForm.BringToFront();
                    editorForm.SeekToLine(lineNumber, offset, length, true);
                    EnableControls(true);
                    allowChangeDocument = true;
                    return;
                }
            }

            EnableControls(true);
        }

        /// <summary>
        ///     Perform jump to error line
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="projectDescriptor"></param>
        /// <param name="lineNumber"></param>

        private void JumpToErrorLineEventHandler(object sender, ProjectDescriptor projectDescriptor, int lineNumber)
        {
            EnableControls(false);
            foreach (EditorForm editorForm in openedEditors)
            {
                if (editorForm.Project.Id.Equals(projectDescriptor.Id))
                {
                    allowChangeDocument = false;
                    editorForm.BringToFront();
                    editorForm.SeekToLine(lineNumber, -1 , -1 , true);
                    EnableControls(true);
                    allowChangeDocument = true;
                    return;
                }
            }

            EnableControls(true);
        }


        /// <summary>
        ///     The event is invoked when user wants to see project results. (The context menu from the
        /// repository explorer)
        /// </summary>
        /// <param name="sender">sender of the event (can be repository explorer and file explorer)</param>
        /// <param name="projectDescriptor">the affected project</param>
        private void ViewProjectResultsHandler(object sender,  ProjectDescriptor projectDescriptor)
        {
            EnableControls(false);

            #region Test if this project is already opened. Compare project ID's
            foreach (ChartForm chartForm in openedCharts)
            {
                if (chartForm.ChartData.Project.Id.Equals(projectDescriptor.Id))
                {
                    chartForm.BringToFront();
                    EnableControls(true);
                    return;
                }
            }
            #endregion

            #region Open project to see results and keep opened form
            ChartForm chart = new ChartForm(new ChartDataObject(projectDescriptor));
            chart.Show(dockPanel);
            chart.FormClosing += new System.Windows.Forms.FormClosingEventHandler(FormClosingEvent);
            openedCharts.Add(chart);
            #endregion

            EnableControls(true);
        }

        /// <summary>
        ///     The event is invoked when user wants to see project results in tabular form. 
        /// The context menu from the repository explorer calls this event handler
        /// </summary>
        /// <param name="sender">sender of the event (can be repository explorer and file explorer)</param>
        /// <param name="projectDescriptor">the affected project</param>
        private void ViewTabularProjectResultsHandler(object sender, ProjectDescriptor projectDescriptor)
        {
            EnableControls(false);

            #region Test if this project is already opened. Compare project ID's
//             foreach (ChartForm chartForm in openedCharts)
//             {
//                 if (chartForm.ChartData.Project.Id.Equals(projectDescriptor.Id))
//                 {
//                     chartForm.BringToFront();
//                     EnableControls(true);
//                     return;
//                 }
//             }
            #endregion
/*
            #region Open project to see results and keep opened form
             TabularForm tabularForm = new TabularForm(new ChartDataObject(projectDescriptor));

            tabularForm.Show(dockPanel);
            tabularForm.FormClosing += new System.Windows.Forms.FormClosingEventHandler(FormClosingEvent);
            //! openedCharts.Add(chart);
            #endregion
*/
            EnableControls(true);
        }

        /// <summary>
        ///     The event is called when user has pressed the refresh button on the 
        /// ChartOptions form.
        /// </summary>
        /// <param name="sender">the event sender</param>
        /// <param name="chartData">the chart data which are changed</param>
        private void RefreshChartHandler (object sender, ChartDataObject chartData)
        {
            EnableControls(false);
            if (currentChartForm != null && chartData != null)
            {
                currentChartForm.ChartData = chartData; 
            }

            EnableControls(true);

        }
        #endregion

        #region Form event handlers
        /// <summary>
        ///     Initialize form items (load some initial data)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_Load(object sender, EventArgs e)
        {
            EnableControls(false);
            mainMenuItemClicked(menuItemViewRepository, null);
            //mainMenuItemClicked(menuItemLocalFiles, null);
            //mainMenuItemClicked(menuItemBuildMessages, null);
            //mainMenuItemClicked(menuItemBuildErrors, null);

            #region Manage visibility of the priveleged menu items
            menuItemManageUsersAndGroups.Visible = WorksessionData.UserInfo.HasPermission(usm.SolDev.Common.Constants.Permissions.UserPermission.ManageUsers);
            #endregion

            EnableControls(true);
        }
        /// <summary>
        ///     Update window related content when user swithces editor windos
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dockPanel_ActiveDocumentChanged(object sender, EventArgs e)
        {
            if (allowChangeDocument == false)
            {
                return;
            }

            if (((WeifenLuo.WinFormsUI.Docking.DockPanel)sender).ActiveDocument is EditorForm)
            {
                currentEditorForm = (EditorForm)((WeifenLuo.WinFormsUI.Docking.DockPanel)sender).ActiveDocument;
                if (codeExplorer != null)
                {
                    if (currentEditorForm != null)
                    {
                        if (codeExplorer.Project == null || currentEditorForm.Project.Id.Equals(codeExplorer.Project.Id) == false)
                        {
                            codeExplorer.ReloadProject(currentEditorForm.Project);
                        }

                    }
                    else
                    {
                        codeExplorer.ReloadProject(null);
                    }
                }
            }
            else if (((WeifenLuo.WinFormsUI.Docking.DockPanel)sender).ActiveDocument is ChartForm)
            {
                currentChartForm = (ChartForm)((WeifenLuo.WinFormsUI.Docking.DockPanel)sender).ActiveDocument;
                if (chartOptionsForm != null)
                {
                    if (currentChartForm != null)
                    {
                        if (chartOptionsForm.ChartData == null || currentChartForm.ChartData.Project.Id.Equals(chartOptionsForm.ChartData.Project.Id) == false)
                        {
                            chartOptionsForm.ChartData = currentChartForm.ChartData;
                        }

                    }
                    else
                    {
                        chartOptionsForm.ChartData = null;
                    }
                }
            }
        }

        /// <summary>
        ///     A hack ... enable disabled controls.
        ///  TODO: Cancel background operation
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tssWaitImage_Click(object sender, EventArgs e)
        {
            EnableControls(true);
        }

        #endregion

        #region Compilation handlers

        /// <summary>
        /// 
        /// </summary>
        /// <param name="compilerProc"></param>
        private delegate usm.SolDev.Common.ProcessCompile StartCompileDelegate(usm.SolDev.Common.ProcessCompile compilerProc);
        private usm.SolDev.Common.ProcessCompile StartCompilation(usm.SolDev.Common.ProcessCompile compilerProc)
        {
            try
            {
                if (compilerProc.Start() == false)
                {
                    buildMessages.AppendMessage("Failed to start compilation");
                    return compilerProc;
                }

                compilerProc.InputStream.Write(compilerProc.ProgramLines);
                compilerProc.InputStream.Write(new char[] { (char)0x1A }, 0, 1);    // write end of stream
                while (compilerProc.HasExited == false) ;

                #region Read DRG & VSP File
                if (compilerProc.Execute && compilerProc.ExitCode == 0)
                {
                    // currentEditorForm.Project.Results
                    // currentEditorForm.Project.Entities
                }
                #endregion

                return compilerProc;

            } catch  (Exception ex)
            {
                if (buildMessages != null)
                {
                    buildMessages.AppendMessage(String.Format("Failed to complete compilation on file {0}, due to compiler internal error : {1}", compilerProc.Application, ex));
                }

                return null;
            }
        }
        
        /// <summary>
        ///     The compilation has been finished.
        /// </summary>
        /// <param name="ar"></param>
        private void StartCompileCallBack(IAsyncResult ar)
        {
            try
            {
                usm.SolDev.Common.ProcessCompile procCompiler = ((StartCompileDelegate)((AsyncResult)ar).AsyncDelegate).EndInvoke(ar);
                if (!IsDisposed && IsHandleCreated)
                {

                    if (procCompiler != null)
                    {
                        BeginInvoke(new AfterCompilationCompletedDelegate(AfterCompilationCompleted), new object[] { true, procCompiler });
                    }
                    else
                    {
                        BeginInvoke(new AfterCompilationCompletedDelegate(AfterCompilationCompleted), new object[] { false, null});
                    }
                    
                }
            }
            catch (Exception ex)
            {
                BeginInvoke(new AfterCompilationCompletedDelegate(AfterCompilationCompleted), new object[] { false, null});
                new SolDevException("Cannot complete compilation", ex);
            }
        }

        /// <summary>
        ///     Add message lines to build messages and error messages window if any error has occured
        /// during compilation
        /// </summary>
        /// <param name="succes"></param>
        private delegate void AfterCompilationCompletedDelegate(bool succes, usm.SolDev.Common.ProcessCompile procCompiler);
        private void AfterCompilationCompleted(bool succes, usm.SolDev.Common.ProcessCompile procCompiler)
        {

            if (buildErrors != null)
            {
                buildErrors.Clear(currentEditorForm.Project);
            }
            else
            {
                buildErrors = new BuildErrors(currentEditorForm.Project);
                buildErrors.Show(dockPanel);

                buildErrors.FormClosing += new System.Windows.Forms.FormClosingEventHandler(FormClosingEvent);
                buildErrors.JumpToErrorLine += new BuildErrors.JumpToErrorLineDelegate(JumpToErrorLineEventHandler);
            }

            if (succes == false)
            {
                
                buildErrors.AppendLine("Failed :(");
                EnableControls(true);
                return;
            }
            
            while (procCompiler.OutputStream.EndOfStream == false)
            {
                string outputLine = procCompiler.OutputStream.ReadLine();
                ProcessOutputLine(outputLine);

                if (procCompiler.ExitCode != 0)
                {
                    buildErrors.AppendLine(outputLine);
                }
            }

            if (procCompiler.ExitCode != 0)
            {
                buildErrors.Activate(); // BringToFront();
            }
            else
            {
                if (procCompiler.Execute)
                {
                    try
                    {
                        TextReader vspTextReader = new StreamReader(new FileStream(String.Format("{0}\\stdinfile.vsp", currentEditorForm.Project.ApplicationPath), FileMode.Open, FileAccess.Read));
                        currentEditorForm.Project.Entities = vspTextReader.ReadToEnd();

                        // load DRG and VSP file
                        try
                        {
                            TextReader drgTextReader = new StreamReader(new FileStream(String.Format("{0}\\stdinfile.drg", currentEditorForm.Project.ApplicationPath), FileMode.Open, FileAccess.Read));
                            currentEditorForm.Project.Results = drgTextReader.ReadToEnd();
                        }
                        catch
                        {
                            throw new SolDevException("Cannot load DRG file content. Results will not be available!");
                        }
                    }
                    catch (SolDevException)
                    {
                    }
                    catch
                    {
                        new SolDevException("Cannot load VSP file content. Results will not be avaialble!");
                    }
                }
            }

            procCompiler.Dispose();
            procCompiler = null;

            EnableControls(true);
        }

        private void ProcessOutputLine( string stringLine)
        {
            if (buildMessages != null)
            {
                buildMessages.AppendMessage(stringLine);
            }
        }
        #endregion

    }
}
